<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=9">
<meta name="generator" content="Doxygen 1.8.13">
<title>OpenCV:简介</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon">
<link href="../../tabs.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css">
<link href="../../stylesheet.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()" onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Introduction(介绍)</div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>OpenCV (开源计算机视觉库:<a href="http://opencv.org">http://opencv.org</a>)是一个开源库，包含数百种计算机视觉算法。该文档描述了所有的OpenCV 2 .x API，它本质上是一个C++ API，而不是基于C的OpenCV 1 .x API（C API被禁止，并且自从OpenCV 2.4发布以来没有用C语言测试)</p>
<p>OpenCV有一个模块化的结构，这意味着这个包包含几个共享的或静态的库。提供以下模块：</p>
<ul>
<li><a class="el" href="../../d0/de1/group__core.html">Core functionality</a>(<b>core核心</b>)-定义基本数据结构的紧凑模块，包括密集多维数组和所有其他模块使用的基本函数。</li>
<li><a class="el" href="../../d7/dbd/group__imgproc.html">Image Processing</a>(<b>imgproc</b>)-图像处理模块，包括线性和非线性图像滤波、几何图像变换（调整大小、仿射和透视扭曲、基于通用表的重新映射）、颜色空间转换、直方图等。</li>
<li><a class="el" href="../../d7/de9/group__video.html">Video Analysis</a>(<b>video视频</b>)-视频分析模块，包括运动估计、背景减法和目标跟踪算法。</li>
<li><a class="el" href="../../d9/d0c/group__calib3d.html">Camera Calibration and 3D Reconstruction</a>(<b>calib3d</b>)-基本的多视图几何算法、单摄像机和立体摄像机标定、物体姿态估计、立体对应算法和三维重建元素。</li>
<li><a class="el" href="../../da/d9b/group__features2d.html">2D Features Framework</a>(<b>features2d</b>)显著特征检测器、描述符和描述符匹配器。</li>
<li><a class="el" href="../../d5/d54/group__objdetect.html">Object Detection</a>(<b>objdetect目标检测</b>)-检测预定义类的对象和实例（例如，人脸、眼睛、马克杯、人、汽车等）。</li>
<li><a class="el" href="../../d7/dfc/group__highgui.html">High-level GUI</a>(<b>highgui</b>)-简单用户界面功能的易用界面。</li>
<li><a class="el" href="../../dd/de7/group__videoio.html">Video I/O</a>(<b>视频IO</b>)-易于使用的视频捕获和视频编解码器接口。</li>
<li>... 其他一些帮助程序模块，如FLANN和Google测试包装器、Python绑定等。</li>
</ul>
<p>本文档的后续章节描述了每个模块的功能。但首先，要确保完全熟悉库中使用的常见API概念。</p>
<h2>API概念</h2>
<h3>cv Namespace</h3>
<p>所有OpenCV类和函数都放在<code>cv</code>命名空间。因此，要从代码中访问此功能，请使用<code>cv::</code>说明符或<code>using namespace cv;</code>指令：</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a>&quot;</span></div><div class="line">...</div><div class="line">cv::Mat H = <a class="code" href="../../d9/d0c/group__calib3d.html#ga4abc2ece9fab9398f2e560d53c8c9780">cv::findHomography</a>(points1, points2, <a class="code" href="../../d9/d0c/group__calib3d.html#gga58a3bc75c7337534ea9c1697b928cae0a724159df258a5d7e29410a6a2f4e6c87">cv::RANSAC</a>, 5);</div><div class="line">...</div></div><!-- fragment --><p>或：</p><div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a>&quot;</span></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line">...</div><div class="line"><a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> H = <a class="code" href="../../d9/d0c/group__calib3d.html#ga4abc2ece9fab9398f2e560d53c8c9780">findHomography</a>(points1, points2, <a class="code" href="../../d9/d0c/group__calib3d.html#gga58a3bc75c7337534ea9c1697b928cae0a724159df258a5d7e29410a6a2f4e6c87">RANSAC</a>, 5 );</div><div class="line">...</div></div><!-- fragment --><p>某些当前或将来的OpenCV外部名称可能与STL或其他库冲突。在这种情况下，请使用显式命名空间说明符来解决名称冲突：</p><div class="fragment"><div class="line">Mat a(100, 100, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>);</div><div class="line"><a class="code" href="../../d2/de8/group__core__array.html#ga1ba1026dca0807b27057ba6a49d258c0">randu</a>(a, Scalar::all(1), Scalar::all(std::rand()));</div><div class="line"><a class="code" href="../../d0/de1/group__core.html#ga4eba02a849f926ee1764acde47108753">cv::log</a>(a, a);</div><div class="line">a /= <a class="code" href="../../d0/de1/group__core.html#ga4eba02a849f926ee1764acde47108753">std::log</a>(2.);</div></div><!-- fragment --><h3>自动内存管理</h3>
<p>OpenCV自动处理所有内存。</p>
<p>首先,std::vector,<a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a>，以及函数和方法使用的其他数据结构具有析构函数，这些析构函数可以在需要时释放底层内存缓冲区。这意味着析构函数并不总是像Mat那样释放缓冲区。它们考虑了可能的数据共享。析构函数递减与矩阵数据缓冲区相关联的引用计数器。当且仅当引用计数器达到零时（也就是说，没有其他结构引用同一个缓冲区时），才释放缓冲区。类似地，复制Mat实例时，不会真正复制任何实际数据。相反，引用计数器会递增，以记住相同数据的另一所有者。还有Mat::clone方法可以创建矩阵数据的完整副本。请参见下面的示例：</p><div class="fragment"><div class="line"><span class="comment">// create a big 8Mb matrix</span></div><div class="line">Mat A(1000, 1000, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga30a562691cc5987bc88eb7bb7a8faf2b">CV_64F</a>);</div><div class="line"></div><div class="line"><span class="comment">// create another header for the same matrix;</span></div><div class="line"><span class="comment">// this is an instant operation, regardless of the matrix size.</span></div><div class="line">Mat B = A;</div><div class="line"><span class="comment">// create another header for the 3-rd row of A; no data is copied either</span></div><div class="line">Mat C = B.row(3);</div><div class="line"><span class="comment">// now create a separate copy of the matrix</span></div><div class="line">Mat D = B.clone();</div><div class="line"><span class="comment">// copy the 5-th row of B to C, that is, copy the 5-th row of A</span></div><div class="line"><span class="comment">// to the 3-rd row of A.</span></div><div class="line">B.row(5).copyTo(C);</div><div class="line"><span class="comment">// now let A and D share the data; after that the modified version</span></div><div class="line"><span class="comment">// of A is still referenced by B and C.</span></div><div class="line">A = D;</div><div class="line"><span class="comment">// now make B an empty matrix (which references no memory buffers),</span></div><div class="line"><span class="comment">// but the modified version of A will still be referenced by C,</span></div><div class="line"><span class="comment">// despite that C is just a single row of the original A</span></div><div class="line">B.release();</div><div class="line"></div><div class="line"><span class="comment">// finally, make a full copy of C. As a result, the big modified</span></div><div class="line"><span class="comment">// matrix will be deallocated, since it is not referenced by anyone</span></div><div class="line">C = C.clone();</div></div><!-- fragment --><p>你看，垫子和其他基本结构的使用很简单。但是在没有考虑自动内存管理的情况下创建的高级类甚至用户数据类型呢？对于他们来说，OpenCV提供了<a class="el" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">cv::Ptr</a>模板类类似于STD::CysDypPTR，来自C++ 11。因此，代替使用普通指针：</p><div class="fragment"><div class="line">T* ptr = <span class="keyword">new</span> T(...);</div></div><!-- fragment --><p>您可以使用:</p><div class="fragment"><div class="line">Ptr&lt;T&gt; ptr(<span class="keyword">new</span> T(...));</div></div><!-- fragment --><p>或:</p><div class="fragment"><div class="line">Ptr&lt;T&gt; ptr = makePtr&lt;T&gt;(...);</div></div><!-- fragment --><p> <code>Ptr&lt;T&gt;</code>封装指向T实例的指针和与该指针关联的引用计数器。看到了吗<a class="el" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">cv::Ptr</a>详细说明。</p>
<h3>输出数据的自动分配</h3>
<p>OpenCV自动释放内存，并且在大多数情况下自动为输出函数参数分配内存。如果一个函数有一个或多个输入数组(<a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a>实例）和一些输出数组，输出数组将自动分配或重新分配。输出数组的大小和类型由输入数组的大小和类型决定。如果需要，这些函数将获取额外的参数，以帮助确定输出数组属性。</p>
<p>例子：</p><div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&quot;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span>, <span class="keywordtype">char</span>**)</div><div class="line">{</div><div class="line">    <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">VideoCapture</a> cap(0);</div><div class="line">    <span class="keywordflow">if</span>(!cap.isOpened()) <span class="keywordflow">return</span> -1;</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frame, edges;</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>(<span class="stringliteral">&quot;edges&quot;</span>, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3acf621ace7a54954cbac01df27e47228f">WINDOW_AUTOSIZE</a>);</div><div class="line">    <span class="keywordflow">for</span>(;;)</div><div class="line">    {</div><div class="line">        cap &gt;&gt; frame;</div><div class="line">        <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>(frame, edges, <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea">COLOR_BGR2GRAY</a>);</div><div class="line">        <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(edges, edges, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(7,7), 1.5, 1.5);</div><div class="line">        <a class="code" href="../../dd/d1a/group__imgproc__feature.html#ga04723e007ed888ddf11d9ba04e2232de">Canny</a>(edges, edges, 0, 30, 3);</div><div class="line">        <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(<span class="stringliteral">&quot;edges&quot;</span>, edges);</div><div class="line">        <span class="keywordflow">if</span>(<a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>(30) &gt;= 0) <span class="keywordflow">break</span>;</div><div class="line">    }</div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --><p>数组帧由<code>&gt;&gt;</code>因为视频捕获模块知道视频帧分辨率和位深度。数组边由cvtColor函数自动分配。它的大小和位深度与输入数组相同。通道数为1，因为颜色转换代码<a class="el" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0a353a4b8db9040165db4dacb5bcefb6ea" title="convert between RGB/BGR and grayscale, color conversions ">cv::COLOR_BGR2GRAY</a>表示颜色到灰度的转换。注意，帧和边在循环体的第一次执行期间仅分配一次，因为所有下一个视频帧具有相同的分辨率。如果您以某种方式更改视频分辨率，阵列将自动重新分配。</p>
<p>该技术的关键组件是Mat::create方法。它采用所需的数组大小和类型。如果数组已经具有指定的大小和类型，则该方法不执行任何操作。否则，它将释放先前分配的数据（如果有的话）（这部分涉及减少引用计数器并将其与零进行比较），然后分配所需大小的新缓冲区。大多数函数为每个输出数组调用Mat::create方法，因此实现了输出数据的自动分配。</p>
<p>这一方案的一些显著例外是<a class="el" href="../../d2/de8/group__core__array.html#ga51d768c270a1cdd3497255017c4504be" title="Copies specified channels from input arrays to the specified channels of output arrays. ">cv::mixChannels</a>,<a class="el" href="../../d1/dd6/classcv_1_1RNG.html#ad26f2b09d9868cf108e84c9814aa682d" title="Fills arrays with random numbers. ">cv::RNG::fill</a>，以及其他一些函数和方法。它们无法分配输出数组，因此必须提前进行分配。</p>
<h3>饱和算法</h3>
<p>作为一个计算机视觉库，OpenCV处理了很多图像像素，这些像素通常以紧凑的、每通道8位或16位的形式进行编码，因此具有有限的值范围。此外，对图像的某些操作（如颜色空间转换、亮度/对比度调整、锐化、复杂插值（双立方、Lanczos））可能会产生超出可用范围的值。如果只存储结果的最低8（16）位，则会产生视觉伪影，并可能影响进一步的图像分析。为了解决这个问题，所谓<em>饱和</em>使用算术。例如，要将操作结果r存储到8位图像中，可以在0..255范围内找到最接近的值：</p>
<p class="formulaDsp">\[I（x，y）=\min（\max（\textrm{round}（r），0），255）\]</p>
<p>类似的规则适用于8位有符号、16位有符号和无符号类型。这种语义在图书馆里随处可见。在C++代码中，使用<code><a class="el" href="../../db/de0/group__core__utils.html#gab93126370b85fda2c8bfaf8c811faeaf" title="Template function for accurate conversion from one primitive type to another. ">cv::saturate_cast</a>&lt;&gt;</code>类似于标准C++的CAST操作的函数。下面是上述公式的实现：</p><div class="fragment"><div class="line">I.at&lt;<a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga65f85814a8290f9797005d3b28e7e5fc">uchar</a>&gt;(y, x) = <a class="code" href="../../db/de0/group__core__utils.html#ga2858f5fe522e46a2e17662669199f6ff">saturate_cast&lt;uchar&gt;</a>(r);</div></div><!-- fragment --><p>其中cv::uchar是OpenCV 8位无符号整数类型。在优化后的SIMD代码中，使用了paddusb、packuswb等SSE2指令。它们有助于实现与C++代码完全相同的行为。</p>
<dl class="section note"><dt>注意</dt><dd>结果为32位整数时不应用饱和。</dd></dl>
<h3>固定像素类型。模板的有限使用</h3>
<p>模板是C++的一大特色，它能够实现非常强大、高效且安全的数据结构和算法。但是，模板的广泛使用可能会极大地增加编译时间和代码大小。此外，当模板被单独使用时，很难将接口和实现分开。这对于基本的算法来说是很好的，但是对于计算机视觉库来说是不好的，因为一个算法可能会跨越数千行代码。正因为如此，而且为了简化其他语言（如Python、Java、Matlab）的绑定开发，这些语言根本没有模板或模板功能有限，当前的OpenCV实现基于多态性和对模板的运行时调度。在那些运行时调度太慢的地方（比如像素访问操作符），不可能（通用的）<code><a class="el" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">cv::Ptr</a>&lt;&gt;</code>或者只是很不方便(<code><a class="el" href="../../db/de0/group__core__utils.html#gab93126370b85fda2c8bfaf8c811faeaf" title="Template function for accurate conversion from one primitive type to another. ">cv::saturate_cast</a>&lt;&gt;()</code>)当前的实现引入了小模板类、方法和函数。在当前OpenCV版本的其他地方，模板的使用是有限的。</p>
<p>因此，库可以操作的基本数据类型的集合是有限的。也就是说，数组元素应具有以下类型之一：</p>
<ul>
<li>8位无符号整数（uchar）</li>
<li>8位有符号整数（schar）</li>
<li>16位无符号整数（ushort）</li>
<li>16位有符号整数（short）</li>
<li>32位有符号整数（int）</li>
<li>32位浮点数（float）</li>
<li>64位浮点数（double）</li>
<li>多个元素的元组，其中所有元素都具有相同的类型（上面的一种）。元素为元组的数组称为多通道数组，与元素为标量值的单通道数组相反。信道的最大可能数量由<a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga3de14a42631396fe0480be69d5d2363f">CV_CN_MAX</a> constant, which is currently set to 512.</li>
</ul>
<p>对于这些基本类型，将应用以下枚举：</p><div class="fragment"><div class="line"><span class="keyword">enum</span> { <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32b18d904ee2b1731a9416a8eef67d06">CV_8U</a>=0, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga26f5e76cbfb2fd9c2ba6fadc6cc19ce3">CV_8S</a>=1, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#gaf55ae5a94c48cae66b96979877576f12">CV_16U</a>=2, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga9d2ee1a8334733dea7482a47a88e0f87">CV_16S</a>=3, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4067910fc388075c3ea3aa14393e83b9">CV_32S</a>=4, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>=5, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga30a562691cc5987bc88eb7bb7a8faf2b">CV_64F</a>=6 };</div></div><!-- fragment --><p>可以使用以下选项指定多通道（n通道）类型：</p>
<ul>
<li><a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga81df635441b21f532fdace401e04f588">CV_8UC1</a>...<a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga44a3c8b22264a8a3e392d8245b0b1d37">CV_64FC4</a>常数（对于从1到4的多个通道）</li>
<li><a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga78c5506f62d99edd7e83aba259250394">CV_8UC(n)</a>...<a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga4213eb262159eb6da4edf8c9255e8244">CV_64FC(n)</a>或<a class="el" href="../../d1/d1b/group__core__hal__interface.html#gab2ebca36079fd923483abee99d7ff40d">CV_MAKETYPE(CV_8U, n)</a>...<a class="el" href="../../d1/d1b/group__core__hal__interface.html#gab2ebca36079fd923483abee99d7ff40d">CV_MAKETYPE(CV_64F, n)</a>编译时通道数大于4或未知时的宏。</li>
</ul>
<dl class="section note"><dt>注意</dt><dd><code><a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga32ec76240e43e4c9c7b2e2785180a7e6">CV_32FC1</a> == <a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>, <a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga15d6109d87682bf909122d0ce51c46a6">CV_32FC2</a> == <a class="el" href="../../d1/d1b/group__core__hal__interface.html#ga56e67b727727f2f9b73a4b62f0c4b2b5">CV_32FC(2)</a> == <a class="el" href="../../d1/d1b/group__core__hal__interface.html#gab2ebca36079fd923483abee99d7ff40d">CV_MAKETYPE(CV_32F, 2)</a></code>，和<code><a class="el" href="../../d1/d1b/group__core__hal__interface.html#gab2ebca36079fd923483abee99d7ff40d">CV_MAKETYPE(depth, n)</a> == ((depth&amp;7) + ((n-1)&lt;&lt;3)</code>. 这意味着常量类型由深度（取最低的3位）和通道数减去1（取下一位）构成<code>log2(CV_CN_MAX)</code>位。</dd></dl>
<p>示例：</p><div class="fragment"><div class="line">Mat mtx(3, 3, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>); <span class="comment">// make a 3x3 floating-point matrix</span></div><div class="line">Mat cmtx(10, 1, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga90505db617283cb4ac14f0870ef57021">CV_64FC2</a>); <span class="comment">// make a 10x1 2-channel floating-point</span></div><div class="line">                           <span class="comment">// matrix (10-element complex vector)</span></div><div class="line">Mat img(<a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(1920, 1080), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga88c4cd9de76f678f33928ef1e3f96047">CV_8UC3</a>); <span class="comment">// make a 3-channel (color) image</span></div><div class="line">                                    <span class="comment">// of 1920 columns and 1080 rows.</span></div><div class="line">Mat grayscale(image.size(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#gab2ebca36079fd923483abee99d7ff40d">CV_MAKETYPE</a>(image.depth(), 1)); <span class="comment">// make a 1-channel image of</span></div><div class="line">                                                            <span class="comment">// the same size and same</span></div><div class="line">                                                            <span class="comment">// channel type as img</span></div></div><!-- fragment --><p>具有更复杂元素的数组不能使用OpenCV构造或处理。此外，每个函数或方法只能处理所有可能数组类型的子集。通常，算法越复杂，支持的格式子集就越小。见以下此类限制的典型示例：</p>
<ul>
<li>人脸检测算法只适用于8位灰度或彩色图像。</li>
<li>线性代数函数和大多数机器学习算法只适用于浮点数组。</li>
<li>基本功能，如<a class="el" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6" title="Calculates the per-element sum of two arrays or an array and a scalar. ">cv::add</a>，支持所有类型。</li>
<li>颜色空间转换函数支持8位无符号、16位无符号和32位浮点类型。</li>
</ul>
<p>每个函数支持的类型子集是根据实际需要定义的，将来可以根据用户请求进行扩展。</p>
<h3>输入阵列和输出阵列</h3>
<p>许多OpenCV函数处理密集的二维或多维数值数组。通常，这类函数以cppMat作为参数，但在某些情况下使用起来更方便<code>std::vector&lt;&gt;</code>（例如，对于点集）或<code><a class="el" href="../../de/de1/classcv_1_1Matx.html" title="Template class for small matrices whose type and size are known at compilation time. ">cv::Matx</a>&lt;&gt;</code>（对于3x3单应矩阵等）。为了避免API中的许多重复，引入了特殊的“代理”类。基本“proxy”类是<a class="el" href="../../dc/d84/group__core__basic.html#ga353a9de602fe76c709e12074a6f362ba">cv::InputArray</a>. 它用于在函数输入上传递只读数组。从InputArray类派生的<a class="el" href="../../dc/d84/group__core__basic.html#gaad17fda1d0f0d1ee069aebb1df2913c0">cv::OutputArray</a>用于指定函数的输出数组。通常，您不应该关心这些中间类型（也不应该显式地声明这些类型的变量）——它们都将自动工作。您可以假设您可以使用<code>Mat</code>,<code>std::vector&lt;&gt;</code>,<code><a class="el" href="../../de/de1/classcv_1_1Matx.html" title="Template class for small matrices whose type and size are known at compilation time. ">cv::Matx</a>&lt;&gt;</code>,<code><a class="el" href="../../d6/dcf/classcv_1_1Vec.html" title="Template class for short numerical vectors, a partial case of Matx. ">cv::Vec</a>&lt;&gt;</code>或<code><a class="el" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">cv::Scalar</a></code>. 当一个函数有一个可选的输入或输出数组，而您没有或不想要一个时，通过<a class="el" href="../../dc/d84/group__core__basic.html#gad9287b23bba2fed753b36ef561ae7346">cv::noArray()</a>.</p>
<h3>错误处理</h3>
<p>OpenCV使用异常来表示严重错误。当输入数据具有正确的格式并且属于指定的值范围，但算法由于某种原因无法成功（例如，优化算法没有收敛）时，它将返回一个特殊的错误代码（通常，只是一个布尔变量）。</p>
<p>例外情况可以是<a class="el" href="../../d1/dee/classcv_1_1Exception.html" title="Class passed to an error. ">cv::Exception</a>类或其衍生物。反过来，<a class="el" href="../../d1/dee/classcv_1_1Exception.html" title="Class passed to an error. ">cv::Exception</a>是std::exception的派生。因此，它可以在代码中优雅地使用其他标准的C++库组件来处理。</p>
<p>通常使用<code><a class="el" href="../../db/de0/group__core__utils.html#ga5b48c333c777666e076bd7052799f891" title="Call the error handler. ">CV_Error(errcode, description)</a></code>宏或其类似printf的<code><a class="el" href="../../db/de0/group__core__utils.html#ga1c0cd6e5bd9a5f915c6cab9c0632f969" title="Call the error handler. ">CV_Error_</a>(errcode, (printf-spec, printf-args))</code>变体，或使用<a class="el" href="../../db/de0/group__core__utils.html#gaf62bcd90f70e275191ab95136d85906b" title="Checks a condition at runtime and throws exception if it fails. ">CV_Assert(condition)</a>检查条件并在不满足条件时抛出异常的宏。对于性能关键型代码，有<a class="el" href="../../db/de0/group__core__utils.html#gafbcb487cba05bd288dbe18c433de4f6f">CV_DbgAssert(condition)</a>只保留在调试配置中。由于自动内存管理，所有中间缓冲区都会在发生突发错误时自动释放。如果需要，只需添加try语句即可捕获异常：</p><div class="fragment"><div class="line"><span class="keywordflow">try</span></div><div class="line">{</div><div class="line">    ... <span class="comment">// call OpenCV</span></div><div class="line">}</div><div class="line"><span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="../../d1/dee/classcv_1_1Exception.html">cv::Exception</a>&amp; e)</div><div class="line">{</div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">char</span>* err_msg = e.<a class="code" href="../../d1/dee/classcv_1_1Exception.html#a9c1e692401016807255e0e6ad562ece9">what</a>();</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot;exception caught: &quot;</span> &lt;&lt; err_msg &lt;&lt; std::endl;</div><div class="line">}</div></div><!-- fragment --><h3>多线程和可重入性</h3>
<p>当前的OpenCV实现是完全可重新输入的。也就是说，可以从不同的线程调用不同类实例的相同函数或相同方法。同样，相同的Mat可以在不同的线程中使用，因为引用计数操作使用特定于体系结构的原子指令。</p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part z s z-->
<hr class="footer"><address class="footer"><small>2021年05月20日 翻译</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
